/*
 * SimpleController
 */

package demo;

import java.awt.Graphics;
import java.awt.Point;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javaPlay.GameEngine;
import javaPlay.GameState;
import javaPlay.Keyboard;
import javaPlay.Scene;
import javaPlay.Sprite;
import javaPlay.TileInfo;

/**
 * 
 * @author VisionLab/PUC-Rio
 */
public class SimpleController implements GameState {
	
	private Sprite playerSprite;
	
	private Sprite enemySprite;
	
	private Player player;
	
	private Enemy[] enemies;
	
	private Scene scene;
	
	private final int NUM_OF_ENEMIES = 2;
	
	private final int TILE_WALL = 1;
	
	private final int TILE_EXIT = 3;
	
	private int[] midx;
	
	private int[] midy;
	
	private final int UP_MID = 0;
	
	private final int DOWN_MID = 1;
	
	private final int LEFT_MID = 2;
	
	private final int RIGHT_MID = 3;
	
	private Score score;
	
	public void load() {
		try {
			playerSprite = new Sprite("walkingplayer.png", 40, 40, 40);
			
			enemySprite = new Sprite("enemy.png", 8, 32, 32);
			
			scene = new Scene();
			scene.loadFromFile("scene.scn");
			
			player = new Player();
			player.setSprite(playerSprite);
			
			scene.addOverlay(player);
			enemies = new Enemy[NUM_OF_ENEMIES];
			
			for (int i = 0; i < NUM_OF_ENEMIES; i++) {
				enemies[i] = new Enemy();
				enemies[i].setSprite(enemySprite);
				scene.addOverlay(enemies[i]);
			}
			
			score = new Score();
			scene.addOverlay(score);
			
			midx = new int[4];
			midy = new int[4];
		} catch (Exception ex) {
			Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
		}
	}
	
	public void unload() {
		
	}
	
	public void start() {
		player.x = 92;
		player.y = 114;
		
		Point startPosEnemy1 = new Point();
		Point endPosEnemy1 = new Point();
		
		startPosEnemy1.x = 251;
		startPosEnemy1.y = 208;
		endPosEnemy1.x = 379;
		endPosEnemy1.y = 208;
		
		enemies[0].setPath(startPosEnemy1, endPosEnemy1);
		
		Point startPosEnemy2 = new Point();
		Point endPosEnemy2 = new Point();
		
		startPosEnemy2.x = 477;
		startPosEnemy2.y = 408;
		endPosEnemy2.x = 666;
		endPosEnemy2.y = 408;
		
		enemies[1].setPath(startPosEnemy2, endPosEnemy2);
	}
	
	@SuppressWarnings("rawtypes")
	public void step(long gameTime, long timeElapsed) {
		Keyboard k = GameEngine.getInstance().getKeyboard();
		
		if (k.isKeyDown(Keyboard.UP_KEY) == true) {
			player.moveUp();
		}
		if (k.isKeyDown(Keyboard.DOWN_KEY) == true) {
			player.moveDown();
		}
		if (k.isKeyDown(Keyboard.LEFT_KEY) == true) {
			player.moveLeft();
		}
		if (k.isKeyDown(Keyboard.RIGHT_KEY) == true) {
			player.moveRight();
		}
		
		player.step(timeElapsed);
		
		Point playerMin = new Point(player.x, player.y);
		Point playerMax = new Point(player.x + 31, player.y + 31);
		
		for (int i = 0; i < NUM_OF_ENEMIES; i++) {
			enemies[i].step(timeElapsed);
			
			Point enemyMin = new Point(enemies[i].x, enemies[i].y);
			Point enemyMax = new Point(enemies[i].x + 31, enemies[i].y + 31);
			
			if (isColliding(playerMin, playerMax, enemyMin, enemyMax) == true) {
				// update Score
				score.setScore(-1);
				// back to start point
				player.x = 92;
				player.y = 114;
				// Shutdown if Score = 0
				if (score.getScore() == 0)
					GameEngine.getInstance().requestShutdown();
				
				return;
			}
		}
		
		Vector tiles = scene.getTilesFromRect(playerMin, playerMax);
		
		for (int i = 0; i < tiles.size(); i++) {
			TileInfo tile = (TileInfo) tiles.elementAt(i);
			
			if ((tile.id == TILE_WALL) && (isColliding(playerMin, playerMax, tile.min, tile.max) == true)) {
				int centerx = playerMin.x / 2 + playerMax.x / 2;
				int centery = playerMin.y / 2 + playerMax.y / 2;
				
				midx[UP_MID] = tile.min.x / 2 + tile.max.x / 2;
				midy[UP_MID] = tile.min.y;
				
				midx[DOWN_MID] = tile.min.x / 2 + tile.max.x / 2;
				midy[DOWN_MID] = tile.max.y;
				
				midx[LEFT_MID] = tile.min.x;
				midy[LEFT_MID] = tile.min.y / 2 + tile.max.y / 2;
				
				midx[RIGHT_MID] = tile.max.x;
				midy[RIGHT_MID] = tile.min.y / 2 + tile.max.y / 2;
				
				int dx = midx[UP_MID] - centerx;
				int dy = midy[UP_MID] - centery;
				int nearestMid = 0;
				double nearestDist = Math.sqrt(dx * dx + dy * dy);
				
				for (int j = 1; j < 4; j++) {
					dx = midx[j] - centerx;
					dy = midy[j] - centery;
					double dist = Math.sqrt(dx * dx + dy * dy);
					
					if (dist < nearestDist) {
						nearestDist = dist;
						nearestMid = j;
					}
				}
				
				switch (nearestMid) {
				case UP_MID:
					player.y = tile.min.y - 32;
					break;
				case DOWN_MID:
					player.y = tile.max.y;
					break;
				case LEFT_MID:
					player.x = tile.min.x - 32;
					break;
				case RIGHT_MID:
					player.x = tile.max.x;
					break;
				}
			} else if (tile.id == TILE_EXIT) {
				GameEngine.getInstance().changeGameState(Global.END_SCREEN_CONTROLLER_ID);
			}
		}
	}
	
	public void draw(Graphics g) {
		scene.draw(g);
	}
	
	public void stop() {
		
	}
	
	private boolean isColliding(Point min1, Point max1, Point min2, Point max2) {
		if (min1.x > max2.x || max1.x < min2.x) {
			return false;
		}
		if (min1.y > max2.y || max1.y < min2.y) {
			return false;
		}
		
		return true;
	}
}
